<template>
  <div class="container" ref="containerRef">
    <Teleport to="body">
      <transition
        @beforeEnter="handleBeforeEnter"
        @enter="handleEnter"
        @afterEnter="handleAfterEnter"
      >
        <div 
          v-if="showMenu" 
          class="context-menu"
          :style="{
            left: x + 'px',
            top: y + 'px'
          }"
        >
          <div
            @click="handleClick(item)"
            class="menu-item"
            v-for="item in menu"
            :key="item.label"
          >
            {{ item.label }}
          </div>
        </div>
      </transition>
    </Teleport>
  </div>
</template>

<script>
import Teleport from './Teleport.vue'
export default {
  name: 'EventContextMenu',
  components: {
    Teleport
  }, 
  data() {
    return {
      x: 0,
      y: 0,
      showMenu: false,
      menu: [],
      func: () => {},
    }
  },

  mounted() {
    document.addEventListener('customEvent', this.handleCustomEvent)
    window.addEventListener('click', this.closeMenu)
    window.addEventListener('contextmenu', this.closeMenu, true)
  },
  unmounted() {
    document.removeEventListener('customEvent', this.handleCustomEvent)
    window.removeEventListener('click', this.closeMenu)
    window.removeEventListener('contextmenu', this.closeMenu, true)
  },
  methods: {
    handleCustomEvent(e) {
      this.closeMenu()
      const data = e.detail
      data.event.preventDefault()
      data.event.stopPropagation()
      this.x = data.event.clientX
      this.y = data.event.clientY
      this.menu = data.menu
      this.func = data.func
      this.openMenu()
    },
    handleClick(item) {
      this.func(item)
    },
    handleBeforeEnter(el) {
      el.style.height = 0
    },
    handleEnter(el) {
      el.style.height = 'auto'
      const h = el.clientHeight
      el.style.height = 0
      requestAnimationFrame(() => {
        el.style.height = h + 'px'
        el.style.transition = '.2s'
      })
    },
    handleAfterEnter(el) {
      el.style.transition = 'none'
    },
    openMenu() {
      this.showMenu = true
    },
    closeMenu() {
      this.showMenu = false
    }
  }
}
</script>

<style scoped>
.container {
  display: contents;
}
.context-menu {
  position: fixed;
  z-index: 3000;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  overflow: hidden;
  .menu-item {
    padding: 0 10px;
    color: #606266;
    font-size: 14px;
    line-height: 30px;
    cursor: pointer;
    &:hover {
      background-color: #f5f7fa;
    }
  }
}
</style>